#include "HTMLizer.h"
#include "StringOps.h"

#include<iostream>

using namespace std;

#include "Keywords.h"
#include "Scope.h"
#include "Symbol.h"
#include "SymbolTable.h"
#include "Tokenizer.h"

HTMLizer::HTMLizer(void)
{
	m_pxCurrentScope = NULL;
	m_eScopeType = Scope::eScopeInvalid;
	m_sFileName = "";
	m_nLines = 0;
	m_bUBoatOutput = false;
}

HTMLizer::~HTMLizer(void)
{
}

void HTMLizer::offScopeEntry(Scope& inNewScope, Scope& inOldScope)
{
	m_pxCurrentScope = &inNewScope;
	m_eScopeType = m_pxCurrentScope->getScopeType();
	createSpanForScope();
}

void HTMLizer::offScopeExit(Scope& inNewScope, Scope& inOldScope)
{
	createSpanEnd();
	m_pxCurrentScope = &inNewScope;
	m_eScopeType = m_pxCurrentScope->getScopeType();
}

void HTMLizer::offNewToken(Scope& inScope, Token& inToken)
{
	std::string sTokenHTML="";
	
	for(size_t i=0; i<inToken.m_sValue.length(); i++)
	{
		char cTest = inToken.m_sValue[i];

		switch (cTest) 
		{
			case '&':
				sTokenHTML += "&amp;";
				break;
			case '<':
				sTokenHTML += "&lt;";
				break;
			case '>':
				sTokenHTML += "&gt;";
				break;
			case '"':
				sTokenHTML += "&quot;";
				break;
			case '\t':
				sTokenHTML += "&nbsp;&nbsp;&nbsp;&nbsp;"; 
				//TODO: Replace with string padding function
				break;
			case ' ':
				sTokenHTML += "&nbsp;";
				break;
			case '\r':
				sTokenHTML = ""; //Otherwise \r\n sequences will produce two <BR/>s 
				//TODO: Replace with lookahead strategy
				break;
			case '\n':
				sTokenHTML ="<BR/>";
				break;
			default:
				sTokenHTML += cTest;
				break;
		}
	}

	switch( m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
	case Scope::eScopePreprocessor:
	case Scope::eScopeLiteral:
		break;

	default:
		if(Keywords::isKeyword(sTokenHTML))
		{
			sTokenHTML = ("<span class=kwrd>" + sTokenHTML + "</span>");
		}
		else
		{
			if(inToken.m_bIsDelimiter) break;

			Symbol xSymbol;
			if(inScope.findSymbol(inToken.m_sValue, xSymbol))
			{
				//<a href="#bookmark">HTML a tag example</a> 
				sTokenHTML="";
				sTokenHTML += "<a href=\"";
				if(m_pxLocation->m_sFileName != xSymbol.m_xDefinition.m_sFileName)
					sTokenHTML += xSymbol.m_xDefinition.m_sFileName;
				
				sTokenHTML += "#SL";
				sTokenHTML += stringify(xSymbol.m_xDefinition.m_nLineNumber);
				sTokenHTML += "\">";
				sTokenHTML += inToken.m_sValue;
				sTokenHTML += "</a>";
			}
		}
	}

    cout<<sTokenHTML;

	char cDelimiter = char(inToken);
	if('\n' == cDelimiter)
		//Intentionally not coupling with switch case, this is not tr functionality
	{
		createNewline();
	}

}

void HTMLizer::createNewline()
{
	createSpanEnd();

	std::string sLineHTML="";
	sLineHTML += "</span></td></tr>\n";
	sLineHTML += "<tr><td><span id= \"SL";
	sLineHTML += stringify(m_pxLocation->m_nLineNumber);
	sLineHTML += "\">";
	cout<<sLineHTML<<endl;

	createSpanForScope();
}

void HTMLizer::createSpanForScope()
{
	switch(m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
		cout << "<span class=comm>";
		break;

	case Scope::eScopePreprocessor:
		cout << "<span class=prep>";
		break;

	case Scope::eScopeLiteral:
		cout << "<span class=litr>";
		break;
	}
}

void HTMLizer::createSpanEnd()
{
	switch(m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
	case Scope::eScopePreprocessor:
	case Scope::eScopeLiteral:
		cout<< "</span>";
		break;
	}
}

void HTMLizer::generateHeader()
{
	cout << "<html>" << endl << "<head>" << endl;
	cout << "<title>" << m_sFileName << "</title>"<<endl;
	cout << "<style>" << endl;
	cout << "BODY{font-family:courier;}"<<endl;
	cout << ".kwrd{color:rgb(0,0,255);}" << endl;
	cout << ".comm{color:rgb(0,128,0);}" << endl;
	cout << ".prep{color:rgb(0,0,255);}" << endl;
	cout << ".litr{color:rgb(163,21,21);}" << endl;
	cout << ".note{color: #FF5500;}" << endl;
	cout << ".lnum{color:rgb(43,145,175);}"<<endl;
	cout << ".p{font-family:courier;}"<<endl;

	if(m_bUBoatOutput)
	{
		cout<<"DIV {border-style:dotted}"<<endl;
		cout<<"#BarMenu {width:100%; font-family:tahoma; background-color:rgb(212,208,200);}"<<endl;
		cout<<"#BarStatus{width:100%; background-color:rgb(212,208,200);}"<<endl;

		cout<<"#PaneUBoat{"<<endl;
		cout<<"height:90%;	width:20%;"<<endl;
		cout<<"margin: 1%;"<<endl;
		cout<<"float:right;"<<endl;
		cout<<"}"<<endl;

		cout<<"#AreaSource{"<<endl;
		cout<<"height:90%;	width:75%;"<<endl;
		cout<<"margin: 1%;"<<endl;
		cout<<"float:left;"<<endl;
		cout<<"overflow:auto;"<<endl;
		cout<<"}"<<endl;

		cout<<"#AreaNavList{"<<endl;
		cout<<"height:150px;	width:90%;"<<endl;
		cout<<"margin: 1%;}"<<endl;

		cout<<"#AreaNotes{"<<endl;
		cout<<"height:250px; width:90%;"<<endl;
		cout<<"margin: 1%;"<<endl;
		cout<<"}"<<endl;
	}
//	cout << "A:link{color:cyan}" <<endl;
//	cout << "A:visited{color:yellow" <<endl;
	cout << "</style>" << endl;

	cout<< "<script type=\"text/javascript\" src=\"prototype.js\"> </script>"<<endl;
	cout<< "<script type=\"text/javascript\" src=\"editinplace.js\"> </script>"<<endl;
	cout<< "</head>"<<endl;

	cout<< "<script type=\"text/javascript\">"<<endl;
    cout<< "    Event.observe(window, 'load', init, false);"<<endl;
    cout<< "    function init() {";
    cout<< "            for (i = 1; i <= " << m_nLines <<"; i++){"<<endl;
    cout<< "            var        locationid='SL'+i;"<<endl;
    cout<< "                    EditInPlace.makeEditable( {"<<endl;
    cout<< "                            type: 'textarea',"<<endl;
    cout<< "							id: locationid,"<<endl;
    cout<< "                            save_url: 'edit.php'"<<endl;
    cout<< "                    } );"<<endl;
    cout<< "            }"<<endl;
    cout<< "    }"<<endl;
	cout<< "</script>"<<endl;
	cout << "<body>" << endl;


	if(m_bUBoatOutput)
	{
		cout<< "<div id=BarMenu>" << endl;
		cout<< "<a id=Item1>File</a>" << endl;
		cout<< "<a id=Item2>Edit</a>" << endl;
		cout<< "<a id=Item3>Show</a>" << endl;
		cout<< "<a id=Item4>Hide</a>" << endl;
		cout<< "</div>" << endl;
		cout<< "<div id=BarStatus>" << endl;
		cout<< "Status Bar" << endl;
		cout<< "</div>" << endl;

		cout<< "<div id=PaneUBoat>" << endl;

		cout<< "<div id=AreaNavList>" << endl;
		cout<< "File List" << endl;
		cout<< "</div>" << endl;

		cout<< "<div id=AreaNotes>" << endl;
		cout<< "Comments For Line" << endl;
		cout<< "</div>" << endl;

		cout<< "</div>" << endl;

		cout<< "<div id=AreaSource>" << endl;
	}

	cout << "<table><tr>" <<endl;

	//Line Number Display
	cout<<"<td><table>"<<endl;
	for(int i=0; i<m_nLines; i++)
		cout<< "<tr><td class=lnum>"<< (i+1) << "</td></tr>" <<endl;
	cout<<"</table></td>"<<endl;

	cout<<"<td><table>"<<endl;
	cout << "<tr><td><span id= \"SL1\">" << endl;

}

void HTMLizer::generateFooter()
{
	cout << "</span></td></tr>" << endl;
	cout << "</table></td>" << endl;
	cout << "</tr></table>" << endl;
	if(m_bUBoatOutput)
		cout<<"</div>"<<endl;
	cout << "</body>" << endl << "</html>" << endl;
}

